#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include "Definitii.h"

unsigned int port_str_to_int(char *port_str)
{
    unsigned int port = 0;    
    int i = 0;
    if (port_str==NULL) 
	{
        return 0;
    }
    while (port_str[i]!='\0') 
	{
        port = port*10 + (port_str[i]-'0');
        i++;
    }
    return port;
}

void port_int_to_str(unsigned int port, char *port_str)
{
    sprintf(port_str, "%u", port);
}

//Convertim sirul ip deoarece functiile netfilter care extrag (decapsuleaza) dintr-un pachet header-ele au urmatorul format
//		static inline unsigned char *skb_mac_header(const struct sk_buff *skb);
//		static inline unsigned char *skb_network_header(const struct sk_buff *skb);
//		static inline unsigned char *skb_transport_header(const struct sk_buff *skb);
unsigned int ip_str_to_hl(char *ip_str) 
{
    /*converteste sirul intr-o matrice de biti: din "131.132.162.25" in [131][132][162][25]*/
    unsigned char ip_array[4];
    int i = 0;
    unsigned int ip = 0;
    if (ip_str==NULL) 
	{
        return 0; 
    }
    memset(ip_array, 0, 4);
    while (ip_str[i]!='.') 
	{
        ip_array[0] = ip_array[0]*10 + (ip_str[i++]-'0');
    }
    ++i;
    while (ip_str[i]!='.')
	{
        ip_array[1] = ip_array[1]*10 + (ip_str[i++]-'0');
	}
    ++i;
    while (ip_str[i]!='.')
	{
        ip_array[2] = ip_array[2]*10 + (ip_str[i++]-'0');
    }
    ++i;
    while (ip_str[i]!='\0')
	{
        ip_array[3] = ip_array[3]*10 + (ip_str[i++]-'0');
    }

    /*converteste din matricea de biti in formatul long*/
    ip = (ip_array[0] << 24);
    ip = (ip | (ip_array[1] << 16));
    ip = (ip | (ip_array[2] << 8));
    ip = (ip | ip_array[3]);
    //printk(KERN_INFO "ip_str_to_hl convert %s to %u\n", ip_str, ip);
    return ip;
}

void ip_hl_to_str(unsigned int ip, char *ip_str) 
{
	//Conversia inversa din matrice de biti in sir.
    unsigned char ip_array[4];
    memset(ip_array, 0, 4);
    ip_array[0] = (ip_array[0] | (ip >> 24));
    ip_array[1] = (ip_array[1] | (ip >> 16));
    ip_array[2] = (ip_array[2] | (ip >> 8));
    ip_array[3] = (ip_array[3] | ip);
    sprintf(ip_str, "%u.%u.%u.%u", ip_array[0], ip_array[1], ip_array[2], ip_array[3]);
}

bool check_ip(unsigned int ip, unsigned int ip_rule, unsigned int mask)
{
    unsigned int tmp = ntohl(ip);    //conversie ip
    int cmp_len = 32;
    int i = 0, j = 0;
    printk(KERN_INFO "compara ip: %u <=> %u\n", tmp, ip_rule);
    if (mask != 0) 
	{
       cmp_len = 0;
       for (i = 0; i < 32; ++i) 
	   {
		   if (mask & (1 << (32-1-i)))
				cmp_len++;
		   else
			   break;
       }
    }

    /*compara cele doua adrese IP*/
    for (i = 31, j = 0; j < cmp_len; --i, ++j) 
	{
        if ((tmp & (1 << i)) != (ip_rule & (1 << i))) 
		{
            printk(KERN_INFO "comparare ip: bitul %d nu se potriveste\n", (32-i));
            return false;
        }
	}
    return true;
}